/*
 * Copyright (C) 2011 Nokia Corporation and/or its subsidiary(-ies).
 * All rights reserved.
 *
 * This file is a part of Harmattan SmashMiner OpenGL game application.
 * 
 * Harmattan SmashMiner OpenGL Example Application version 1.0.0
 *  
 * Latest update: 15.4.2011
 *
 * The Harmattan SmashMiner OpenGL example application demonstrates how to use 
 * the OpenGL ES in Harmattan devices.
 *
 * This example is provided as a starting point for 3rd party
 * developers (you) to ease the implementation of OpenGL based 
 * games. Ideas, parts of code or methodologies that this
 * example application uses can be freely used without restrictions.
 *
 * See file README.txt how to build and compile this example application
 * in the Harmattan SDK environment. 
 * 
 * See file INSTALL.txt to find out what is required to run this
 * application and how to install the application to the device or
 * alternatively in QEMU-emulator.
 *
 * The LICENSE.txt file explains the license this software is provided
 * with. A copy of the same license is included in this source file.
 * 
 */

/*
 * Copyright (C) 2011 by Nokia Corporation.
 *
 * Permission is hereby granted, free of charge, to any person obtaining a copy
 * of this software and associated documentation files (the "Software"), to deal
 * in the Software without restriction, including without limitation the rights
 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
 * copies of the Software, and to permit persons to whom the Software is
 * furnished to do so, subject to the following conditions:
 *
 * The above copyright notice and this permission notice shall be included in
 * all copies or substantial portions of the Software.
 *
 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
 * THE SOFTWARE.
 */

/**
\file main.qml
\brief The main menu of the SmashMiner game.

This is the QML mainview from where all the other views are opened,
game play is started and the application is exited.

Main view contains the following menu views:
- Settings.qml
- Controls.qml
- HighScores.qml
- Help.qml

\par Tutorials

\ref addGameMenu

\ref removeGameMenu
*/

/**
\page addGameMenu Adding Top Level Game Menu

Here are the instructions for adding a new Qt Quick top level game menu.
Adding \c Controls.qml menu is used as an example.

These instructions focus on features common on all menu views, not the features specific only to the Controls view.

\section createNewMenuViewToQML Creating New Menu View

First create a new QML file \c Controls.qml for the menu view.

Next create an \c Item with id controlsView in the previously created QML file:
\code
...
Item {
    id: controlsView

    signal back()

    property int marginsVertical: height/20
    property int headerHeight: marginsVertical*2
    property int marginsHorizontal: headerHeight+marginsVertical
...
\endcode
This \c Item contains all the QML elements at Controls view.

There must be a \c signal \c back() in the \c Item for returning to the main view.
Then the \c properties for vertical and horizontal margins and for the height of the header are needed.

Next add the background \c Image element:
\code
...
    Image {
        id: background
        anchors.fill: parent
        source: "qrc:/images/1024x512_01.jpg"
    }
...
\endcode
The anchor \c anchors.fill: \c parent is used that background image fills the entire screen.
Source \c source: \c "qrc:/images/1024x512_01.jpg" for the image is get from the resources.

Then add a view header:
\code
...
    ViewHeader {
        id: controlsHeader
        heading: qsTr("CONTROLS")
    }
...
\endcode
Source code for the \c ViewHeader element is in the \c ViewHeader.qml file.

Then for the actual content of the Controls view add a \c Rectangle element:
\code
...
    Rectangle {
        id: rectangleControlHelp

        width: parent.width
        anchors { left: parent.left; right: parent.right; leftMargin: marginsHorizontal; rightMargin: marginsHorizontal;
            top: controlsHeader.bottom; bottom: controlsFooter.top }
        color: "black"
        border { width: 5; color: "#333333" }
...
\endcode
All the actual content for this specific view is shown inside this \c Rectangle element.

\c Rectangle has a black backgound and a border around it.
It is anchored to the view \c Item but has margins so that the background \c Image is seen arond the \c Rectangle.

Then add the following code to the \c Item is \c ViewFooter:
\code
...
    ViewFooter {
        id: controlsFooter

        width: parent.width
        height: headerHeight

        onBackClicked: {
            soundEngine.playMenuSound();
            back();
            if (controlPages.currentPage != 1) {
                controlPages.currentPage = 1;
            }
        }
    } // controlsFooter
...
\endcode
the source code for the footer is in the file \c ViewFooter.qml.

Footer contains the "Back" button.
When the button is clicked, slot \c onBackClicked receives the signal from click.
Then the slot \c onBackClicked emits a signal \c back() which goes back to the main view.

Finally add all the needed QML elements inside the previously created \c Rectangle.

Next edit the \c main.qml file to be able to display the previously created view.

\section createMainMenuImages Creating Main Menu Images

At first create new main menu images.
There must be one image for main menu. Also new image for each menu selection must be created.
The currently selected menu is highlighted at the menu selection images.

Main menu image \c mainmenu.png is at the project folder under \c ./qml/smashminer/pics.

The new highlighted menu image \c mainmenu_controls_selected.png is copied also to folder \c ./qml/smashminer/pics.
Also the new menu images for old highlighted menus must be copied also to folder \c ./qml/smashminer/pics.

\section addMenuImageFileToResources Adding Menu Image File To Resources

Next thing is to add a new highlighted menu image file to resources so that it can be referenced from the QML.

Edit the resource file \c smashminer.qrc.
Add \c mainmenu_controls_selected.png file to the resources under \c images resource prefix.

Add alias \c "mainmenu_controls_selected.png" for the resource file.

Now the resource file can be referenced from the \c main.qml.

\section addNewMenuSelectionToQML Adding New Menu Item To QML Main Menu

First the \c numberOfMenuSelections \c property must be increased under the \c mainview \c Item:
\code
...
property int numberOfMenuSelections: 6
...
\endcode
The \c numberOfMenuSelections is used to calculate \c menuMouseAreaHeight \c property.

Next add the \c MouseArea for opening the \c Controls.qml view when receiving \c clicked() \c signal:
\code
...
        MouseArea {
            id: mouseAreaControls
            anchors { top: mouseAreaSettings.bottom; topMargin: menuMouseAreaMargin; bottomMargin: menuMouseAreaMargin}
            width: parent.width
            height: menuMouseAreaHeight
            onClicked: {
                showSubMenu("qrc:/images/mainmenu_controls_selected.png", controlsView);
            }
        }
...
\endcode
When mouse area is clicked the function \c showSubMenu() changes menu image to the highlighted version and displays the \c controView.

Next thing is to add actual \c Controls element:
\code
...
    Controls {
         id: controlsView
         x: -mainview.width
         onBack: {
            animBackFromMenu.start();
            animBackgroundFromMenu.start();
        }
    }
...
\endcode
Id of the \c Controls element is \c controlsView which is used when referencing to it from javasript code.

Last thing is to add to \c function \c hideSubMenus() hiding of the \c controlsView:
\code
...
        controlsView.visible = false;
...
\endcode
Now the Controls menu selection is working and the Controls view can be opened from the main menu.
*/

/**
\page removeGameMenu Removing Top Level Game Menu

Here are the instructions for removing the Qt Quick top level game menu.
Removing \c Controls.qml menu is used as an example.

\section removeMainMenuImages Removing Main Menu Images

There must be one image for the main menu. Also a new image for each menu selection must be created.
The currently selected menu is highlighted at the menu selection images.

Main menu image \c mainmenu.png is at the project folder under \c ./qml/smashminer/pics.

The old highlighted menu image \c mainmenu_controls_selected.png is removed from folder \c ./qml/smashminer/pics.
The new menu images for old remaining highlighted menus are copied to folder \c ./qml/smashminer/pics.

\section removeMenuImageFileFromResources Removing Menu Image File From Resources

Next thing is to remove the old highlighted menu image file from resources.

Then edit the resource file \c smashminer.qrc.
Remove \c mainmenu_controls_selected.png file from the resources under \c images resource prefix.

\section removeMenuSelectionFromQML Removing Menu Item From QML Main Menu

First the \c numberOfMenuSelections \c property must be decreased from 6 to 5 under the \c mainview \c Item:
\code
...
property int numberOfMenuSelections: 5
...
\endcode
The \c numberOfMenuSelections is used to calculate \c menuMouseAreaHeight \c property.

Next remove the \c MouseArea for opening the \c Controls.qml view when receiving \c clicked() \c signal:
\code
...
        MouseArea {
            id: mouseAreaControls
            anchors { top: mouseAreaSettings.bottom; topMargin: menuMouseAreaMargin; bottomMargin: menuMouseAreaMargin}
            width: parent.width
            height: menuMouseAreaHeight
            onClicked: {
                showSubMenu("qrc:/images/mainmenu_controls_selected.png", controlsView);
            }
        }
...
\endcode
When the mouse area is clicked the function \c showSubMenu() changes the menu image to the highlighted version and displays the \c controView.

Next remove the actual \c Controls element:
\code
...
    Controls {
         id: controlsView
         x: -mainview.width
         onBack: {
            animBackFromMenu.start();
            animBackgroundFromMenu.start();
        }
    }
...
\endcode

Then remove from \c function \c hideSubMenus() hiding of the \c controlsView:
\code
...
        controlsView.visible = false;
...
\endcode

Finally remove the file \c Controls.qml.
Now the main menu has only 5 remaining menu items.
*/


import Qt 4.7

Item {
    id: mainview

    // Is the main view currently visible
    property bool mainViewVisible: true
    // Do the main menu fade out when starting game
    property bool doFadeOutEffect: true
    // Length of the menu fade out effect
    property int fadeOutDurationMs: 400
    // Top and bottom margins of the main menu for mouse areas
    property int menuMouseTopBottomMargin: mainMenuImage.height/10
    // Margins between the menu mouse areas
    property int menuMouseAreaMargin: menuMouseTopBottomMargin/6
    // Heights of the main menu mouse areas. No marging included.
    property int menuMouseAreaHeightWithoutMargins: mainMenuImage.height-(2*menuMouseTopBottomMargin)
    // number of selections at the main menu
    property int numberOfMenuSelections: 6
    // Heights of the main menu mouse areas. With margins
    property int menuMouseAreaHeight: (menuMouseAreaHeightWithoutMargins/numberOfMenuSelections)-menuMouseAreaMargin
    // Background menu x value stored for PropertyAnimation animBackgroundFromMenu
    property int storedBackgroundX: 0

    // Hides all submenus an sets mainView visible
    function hideSubMenus() {
        settingsView.visible = false;
        controlsView.visible = false;
        highScoreView.visible = false;
        helpView.visible = false;

        mainViewVisible = true;
    }

    // Shows sub menu.
    function showSubMenu(source, view) {
        mainMenuImage.source = source;
        animMainMenuImage.start();

        hideSubMenus();
        mainViewVisible = false;

        animToSubMenu.start();
        view.visible = true;

        animBackgroundToSubMenu.start();
        soundEngine.playMenuSound();
    }


    // Resizes the QML views when the GameAppViewer::notifyResize signal is received.
    function onResize(w, h) {

        console.log("main.qml : onResize() " + w + " " + h);

        if (!mainViewVisible) {
            console.log("main.qml : onResize() : setting x = " + width);
            x = width;
        }

        // scale the background image as in the game.
        //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
        // see GameWidget::GLes2InitBackGround() for the related code.

        gameAppViewer.getTitleHeight();
        //console.log("main.qml : titleHeight= " + titleHeight);

        var totalHeight = titleHeight + h;

        var tmp1 = 1708.0 / 960.0;
        var tmp2 = w / totalHeight;

        var startX;
        var startY;

        var rangeX;
        var rangeY;

        if (tmp1 < tmp2) {
            var aspectRatioFix = 1.0 - tmp1 / tmp2;
            //console.log("main.qml : using Y-aspectRatioFix " + aspectRatioFix);

            startX = 0.0;
            startY = 1.0 - aspectRatioFix * 0.50;

            rangeX = +1.0;
            rangeY = -1.0 + aspectRatioFix;
        } else {
            var aspectRatioFix = 1.0 - tmp2 / tmp1;
            //console.log("main.qml : using X-aspectRatioFix " + aspectRatioFix);

            startX = 0.0 + aspectRatioFix * 0.50;
            startY = 1.0;

            rangeX = +1.0 - aspectRatioFix;
            rangeY = -1.0;
        }

        //console.log("startX= " + startX + " startY= " + startY + " rangeX= " + rangeX + " rangeY= " + rangeY);

        // up to here we have the same results as in game background code.
        // invert the Y values and chop away the area under titlebar.

        startY = 1.0 - startY;
        var startYmod = startY + titleHeight / h;

        rangeY = -rangeY;
        var rangeYmod = rangeY - titleHeight / totalHeight;

        // these formulas seem to work exactly, even though
        // the sum below does not add up to one exactly...

        //console.log("the sum is now " + (startYmod + rangeYmod + startY));
        //console.log("startX= " + startX + " startY= " + startY + " rangeX= " + rangeX + " rangeY= " + rangeY);

        background.width = w / rangeX;
        background.x = -background.width * startX;

        background.height = h / rangeYmod;
        background.y = -(h / rangeY) * startYmod;

        //console.log("background position = " + background.x + " " + background.y);
        //console.log("background size = " + background.width + " " + background.height);

        storedBackgroundX = background.x;
    }

    // Sets the new high score for the highScoreView.
    // Receives signal newHighScore(score, timeString) emitted from the GameAppViewer
    function newHighScore(score, time) {
        //console.log("main.qml newHighScore(", score,",",time,")")
        highScoreView.hasHighScore = true;
        highScoreView.newHighScore = score;
        highScoreView.newHighScoreTime = time;
        gameOver();
    }

    // Sets QML view to game over state
    // Receives signal gameOver() emitted from the GameAppViewer
    function gameOver() {
        //console.log("main.qml gameOver()")
        highScoreView.isGameOver = true;

        hideSubMenus();
        mainViewVisible = false;

        highScoreView.visible = true;
        animBackgroundToSubMenu.start();

        mainMenuImage.opacity = 1;
        mainview.x = mainview.width;
    }

    // Starts the new game
    function startGame() {
        timerPlay.start();
    }

    width: viewWidth
    height: viewHeight

    // Different views - Sub menus
    Settings {
        id: settingsView
        x: -mainview.width
        onBack: {
            animBackFromMenu.start();
            animBackgroundFromMenu.start();
        }
    }

    Controls {
         id: controlsView
         x: -mainview.width
         onBack: {
            animBackFromMenu.start();
            animBackgroundFromMenu.start();
        }
    }

    HighScores {
         id: highScoreView
         x: -mainview.width
         onBack: {
             animBackFromMenu.start();
             animBackgroundFromMenu.start();
        }
    }

    Help {
         id: helpView
         x: -mainview.width
         onBack: {
             animBackFromMenu.start();
             animBackgroundFromMenu.start();
         }
    }

    // Main menu bacground image
    Image {
        id: background
        source: "qrc:/images/1024x512_01.jpg"
        z: -10
    }

    // Main menu
    Image {
        id: mainMenuImage
        anchors.fill: parent
        source: "qrc:/images/mainmenu.png"

        // Mouse areas for all the main menu items
        MouseArea {
            id: mouseAreaPlay
            anchors { top: parent.top; topMargin: menuMouseTopBottomMargin; bottomMargin: menuMouseAreaMargin}
            width: parent.width
            height: menuMouseAreaHeight
            onClicked: {
                //console.log("Play button clicked");
                mainMenuImage.source = "qrc:/images/mainmenu_play_selected.png";

                if (doFadeOutEffect) {
                    fadeMainMenuImage.start();
                    doFadeOutEffect = false;
                }

                soundEngine.playMenuSound();
                startGame();
            }
        }
        MouseArea {
            id: mouseAreaSettings
            anchors { top: mouseAreaPlay.bottom; topMargin: menuMouseAreaMargin; bottomMargin: menuMouseAreaMargin }
            width: parent.width
            height: menuMouseAreaHeight
            onClicked: {
                showSubMenu("qrc:/images/mainmenu_settings_selected.png", settingsView);
            }
        }
        MouseArea {
            id: mouseAreaControls
            anchors { top: mouseAreaSettings.bottom; topMargin: menuMouseAreaMargin; bottomMargin: menuMouseAreaMargin}
            width: parent.width
            height: menuMouseAreaHeight
            onClicked: {
                showSubMenu("qrc:/images/mainmenu_controls_selected.png", controlsView);
            }
        }
        MouseArea {
            id: mouseAreaHighScores
            anchors { top: mouseAreaControls.bottom; topMargin: menuMouseAreaMargin; bottomMargin: menuMouseAreaMargin}
            width: parent.width
            height: menuMouseAreaHeight
            onClicked: {
                showSubMenu("qrc:/images/mainmenu_scores_selected.png", highScoreView);
            }
        }
        MouseArea {
            id: mouseAreaHelp
            anchors { top: mouseAreaHighScores.bottom; topMargin: menuMouseAreaMargin; bottomMargin: menuMouseAreaMargin}
            width: parent.width
            height: menuMouseAreaHeight
            onClicked: {
                showSubMenu("qrc:/images/mainmenu_help_selected.png", helpView);
            }
        }
        MouseArea {
            id: mouseAreaExit
            anchors { topMargin: menuMouseAreaMargin; bottom: mainMenuImage.bottom; bottomMargin: menuMouseTopBottomMargin }
            width: parent.width
            height: menuMouseAreaHeight
            onClicked: {
                mainMenuImage.source = "qrc:/images/mainmenu_exit_selected.png";

                fadeMainMenuImage.start();
                soundEngine.playMenuSound();
                timerExit.start();
            }
        }
    } // mainMenuImage

    // Timer to start the new game.
    // Game is started delayed because of the menu fade out effect
    Timer {
        id: timerPlay
        interval: fadeOutDurationMs + 50
        onTriggered: {
            gameAppViewer.enterGameMode();
            mainMenuImage.source = "qrc:/images/mainmenu.png";
            mainMenuImage.opacity = 1;
        }
    }

    // Timer to exit the application.
    // Application is exited with delay because of the menu fade out effect
    Timer {
        id: timerExit
        interval: fadeOutDurationMs + 50
        onTriggered: Qt.quit()
    }

    // Animations
    PropertyAnimation { id: animToSubMenu; target: mainview; properties: "x"; to: mainview.width; duration: 500 }

    // To animate back from submenu
    SequentialAnimation {
        id: animBackFromMenu
        PropertyAnimation { target: mainview; properties: "x"; to: 0; duration: 500 }
        ScriptAction { script: hideSubMenus(); }
    }

    // Animations to slide to submenu and slide back to mainmenu
    PropertyAnimation { id: animBackgroundToSubMenu; target: background; properties: "x"; to: 0; duration: 500 }
    PropertyAnimation { id: animBackgroundFromMenu; target: background; properties: "x"; to: storedBackgroundX; duration: 500 }

    // Animation to switch main menu image back from current selected menu item image
    PropertyAnimation { id: animMainMenuImage; target: mainMenuImage; properties: "source"; to: "qrc:/images/mainmenu.png"; duration: 500 }
    // Animation to fade out main menu image
    PropertyAnimation { id: fadeMainMenuImage; target: mainMenuImage; properties: "opacity"; to: 0; duration: fadeOutDurationMs }
}
